﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using Infrastructure.Library;

namespace Finance.Core.Provider.XmlProvider
{
    public partial class XmlProvider : FinanceProvider
    {
        #region Abstract
        public override void Insert(FinanceItem item)
        {
            var list = FinanceItem.List;
            list.Add(item);

            this.WritePictureFile(list);
        }

        public override void Delete(FinanceItem item)
        {
            var list = FinanceItem.List;
            list.Remove(item);
            this.WritePictureFile(list);
        }

        public override void Update(FinanceItem item)
        {
            var list = FinanceItem.List;
            list.Remove(item);
            list.Add(item);
            this.WritePictureFile(list);
        }

        public override List<FinanceItem> GetAllFinance()
        {
            var list = new List<FinanceItem>();
            var fileName = this.StorageFolder + typeof(FinanceItem).Name + ".xml";
            if (!File.Exists(fileName))
            {
                return list;
            }
            try
            {
                var doc = new XmlDocument();
                doc.Load(fileName);

                var nodes = doc.SelectNodes("Finance/Item");
                if (nodes != null)
                {
                    nodes.Cast<XmlNode>().ToList().ForEach(node =>
                        {
                            FinanceItem item = new FinanceItem();
                            
                            item.ID = node.Attributes["ID"] == null ? Guid.NewGuid().ToString() : node.Attributes["ID"].InnerText;
                            item.Date = node.Attributes["Date"] == null ? System.DateTime.MinValue : DateTime.Parse(node.Attributes["Date"].InnerText);
                            item.Type = node.Attributes["Type"] == null ? FinanceType.UNKNOWN : (FinanceType)Enum.Parse(typeof(FinanceType), node.Attributes["Type"].InnerText);
                            item.Amount = node.Attributes["Amount"] == null ? 0 : Decimal.Parse(node.Attributes["Amount"].InnerText);
                            item.Desc = node.Attributes["Desc"] == null ? null : node.Attributes["Desc"].InnerText;
                            GetBusinessBase<FinanceItem, String>(item, node);
                            list.Add(item);
                        });
                }
                list.Sort();
            }
            catch (Exception ex)
            {
                UtilLib.Util.Log(UtilLib.LogLevel.Error, ex);
            }
            return list;
        }

        public override FinanceItem GetFinanceItem(string id)
        {
            var pic = FinanceItem.List.Find(p => p.ID == id) ?? new FinanceItem();
            pic.MarkOld();
            return pic;
        }

        public override void SaveAllFinance()
        {
            this.WritePictureFile(FinanceItem.List);
        }
        #endregion

        /// <summary>
        /// The write blog roll file.
        /// </summary>
        /// <param name="blogRollItems">
        /// The blog roll items.
        /// </param>
        private void WritePictureFile(List<FinanceItem> list)
        {
            var fileName = this.StorageFolder + typeof(FinanceItem).Name + ".xml";
            if (!System.IO.Directory.Exists(this.StorageFolder))
                System.IO.Directory.CreateDirectory(this.StorageFolder);
            if (System.IO.File.Exists(fileName))
            {
                FileStream stream = System.IO.File.Create(fileName);
                stream.Close();
                stream.Dispose();
            }
            using (var writer = new XmlTextWriter(fileName, Encoding.UTF8))
            {
                writer.Formatting = Formatting.Indented;
                writer.Indentation = 4;
                writer.WriteStartDocument(true);
                writer.WriteStartElement("Finance");
                list.ForEach(item =>
                {
                    writer.WriteStartElement("Item");
                    writer.WriteAttributeString("ID", item.ID.ToString());
                    writer.WriteAttributeString("Date", item.Date.ToString());
                    writer.WriteAttributeString("Type", item.Type.ToString());
                    writer.WriteAttributeString("Amount", item.Amount.ToString());
                    writer.WriteAttributeString("Desc", item.Desc);
                    WriteBusinessBase<FinanceItem, String>(item, writer);
                    writer.WriteEndElement();
                    item.MarkOld();
                });
                writer.WriteEndElement();
            }
        }

        private void GetBusinessBase<T, TKey>(T item, XmlNode node) where T : BusinessBase<T, TKey>, new()
        {
            DateTime dateCreated = DateTime.MinValue;
            if (node.Attributes["DateCreated"] == null || !DateTime.TryParse(node.Attributes["DateCreated"].InnerText, out dateCreated))
                item.DateCreated = DateTime.MinValue;
            else
                item.DateCreated = dateCreated;
            DateTime dateModified = DateTime.MinValue;
            if (node.Attributes["DateModified"] == null || !DateTime.TryParse(node.Attributes["DateModified"].InnerText, out dateModified))
                item.DateModified = DateTime.MinValue;
            else
                item.DateModified = dateModified;
        }

        private void WriteBusinessBase<T, TKey>(T item, XmlTextWriter writer) where T : BusinessBase<T, TKey>, new()
        {
            writer.WriteAttributeString("DateCreated", item.DateCreated.ToString());
            writer.WriteAttributeString("DateModified", item.DateModified.ToString());
        }

    }
}
